package com.mdd.front.controller;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.constraints.NotNull;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.mdd.common.enums.OrderEnum;
import com.mdd.front.vo.order.OrderListVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.Assert;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import com.alibaba.fastjson.JSONObject;
import com.alipay.api.AlipayApiException;
import com.alipay.api.internal.util.AlipaySignature;
import com.github.binarywang.wxpay.bean.notify.SignatureHeader;
import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyV3Result;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.github.binarywang.wxpay.service.WxPayService;
import com.github.wxpay.sdk.WXPay;
import com.github.wxpay.sdk.WXPayUtil;
import com.ijpay.core.kit.HttpKit;
import com.ijpay.core.kit.WxPayKit;
import com.mdd.common.aop.NotLogin;
import com.mdd.common.core.AjaxResult;
import com.mdd.common.entity.RechargeOrder;
import com.mdd.common.entity.order.Order;
import com.mdd.common.enums.ClientEnum;
import com.mdd.common.enums.PaymentEnum;
import com.mdd.common.exception.OperateException;
import com.mdd.common.mapper.RechargeOrderMapper;
import com.mdd.common.mapper.order.OrderMapper;
import com.mdd.common.pay.alipay.AliPayConfigUtils;
import com.mdd.common.pay.wxpay.WxConfig;
import com.mdd.common.pay.wxpay.WxPayConfigUtils;
import com.mdd.common.plugin.alipay.AliPayDriver;
import com.mdd.common.plugin.wechat.WxPayDriver;
import com.mdd.common.util.RedisUtils;
import com.mdd.common.util.StringUtils;
import com.mdd.common.util.em.EMServiceUtil;
import com.mdd.front.LikeFrontThreadLocal;
import com.mdd.front.service.IPayService;
import com.mdd.front.validate.PayVipValidate;
import com.mdd.front.validate.PaymentValidate;
import com.mdd.front.vo.pay.PayStatusVo;
import com.mdd.front.vo.pay.PayWayListVo;

import cn.hutool.core.util.StrUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;

@RestController
@RequestMapping("/api/pay")
@Api(tags = "支付管理")
public class PayController {

	@Resource
	RechargeOrderMapper rechargeOrderMapper;

	@Resource
	OrderMapper orderMapper;

	@Resource
	IPayService iPayService;

	@Autowired
	WxConfig wxConfig;

	@Autowired
	EMServiceUtil eMServiceUtil;
	
	@GetMapping("/testMsg")
	@ApiOperation("测试发送消息")
	@NotLogin
	public AjaxResult<Object> testMsg(String username){
		eMServiceUtil.sendNoticeOfReceipt(username, "本次获取金币100，现金200");
		return AjaxResult.success();
	}
	
	@GetMapping("/payWay")
	@ApiOperation("支付方式")
	public AjaxResult<PayWayListVo> payWay(@Validated @NotNull(message = "from参数丢失") @RequestParam String from,
			@Validated @NotNull(message = "orderId参数丢失") @RequestParam Integer orderId) {
		Integer terminal = LikeFrontThreadLocal.getTerminal();
		Integer userId = LikeFrontThreadLocal.getUserId();

		PayWayListVo list = iPayService.payWay(from, orderId, terminal, userId);
		return AjaxResult.success(list);
	}

	@GetMapping("/payStatus")
	@ApiOperation(("支付状态"))
	public AjaxResult<PayStatusVo> payStatus(@Validated @NotNull(message = "from参数丢失") @RequestParam String from,
			@Validated @NotNull(message = "orderId参数丢失") @RequestParam Integer orderId) {
		PayStatusVo vo = iPayService.payStatus(from, orderId);
		return AjaxResult.success(vo);
	}

	@GetMapping("/getMchId")
	@ApiOperation("获取商户号")
	public AjaxResult<Object> getMchId(@Validated @NotNull(message = "payWay参数丢失") @RequestParam Integer payWay){
		Map<String, String> map = iPayService.getMchId(payWay);
		return AjaxResult.success(map);
	}

	@PostMapping("/prepay")
	@ApiOperation("发起支付")
	public AjaxResult<Object> prepay(@Validated @RequestBody PaymentValidate requestObj) {
		// 接收参数
		String scene     = requestObj.getScene();
		Integer payWay   = requestObj.getPayWay();
		Integer orderId  = requestObj.getOrderId();
		Integer terminal = LikeFrontThreadLocal.getTerminal();

		// 订单处理
		int payStatus = 0;
		switch (scene) {
		case "recharge":
			RechargeOrder rechargeOrder = rechargeOrderMapper.selectById(orderId);

			Assert.notNull(rechargeOrder, "订单不存在");
			Assert.isTrue(!payWay.equals(PaymentEnum.WALLET_PAY.getCode()), "支付类型不被支持");

			requestObj.setUserId(rechargeOrder.getUserId());
			requestObj.setOutTradeNo(rechargeOrder.getOrderSn());
			requestObj.setOrderAmount(rechargeOrder.getOrderAmount());
			requestObj.setDescription("余额充值");
			requestObj.setAttach("recharge");
			payStatus = rechargeOrder.getPayStatus();

			rechargeOrder.setPayWay(payWay);
			rechargeOrderMapper.updateById(rechargeOrder);
			break;
		case "order":
			Order order = orderMapper.selectById(orderId);
			Assert.notNull(order, "订单不存在");
			requestObj.setUserId(order.getUserId());
			requestObj.setOutTradeNo(order.getOrderSn());
			requestObj.setOrderAmount(order.getNeedPayMoney());
			requestObj.setDescription("订单下单");
			requestObj.setAttach("order");
			payStatus = order.getPayIs();
			order.setPayWay(payWay);
			orderMapper.updateById(order);
			List<Order> list = new ArrayList<>();
			list = orderMapper.selectList(new QueryWrapper<Order>()
					.eq("is_delete", 0)
					.eq("main_id", order.getOrderSn()));
			for(Order order2 : list){
				order2.setPayWay(payWay);
				orderMapper.updateById(order2);
			}
			break;
		}

		// 订单校验
		if (payStatus != 0) {
			throw new OperateException("订单已支付");
		}

		// 发起支付
		Object result = iPayService.prepay(requestObj, terminal);
		return AjaxResult.success(result);
	}

	@NotLogin
	@PostMapping("/notifyMnp")
	@ApiOperation("微信支付回调")
	public AjaxResult<Object> notifyMnp(@RequestBody String jsonData, HttpServletRequest request) throws WxPayException {
		// 构建签名
		SignatureHeader signatureHeader = new SignatureHeader();
		signatureHeader.setSignature(request.getHeader("wechatpay-signature"));
		signatureHeader.setNonce(request.getHeader("wechatpay-nonce"));
		signatureHeader.setSerial(request.getHeader("wechatpay-serial"));
		signatureHeader.setTimeStamp(request.getHeader("wechatpay-timestamp"));

		System.out.println("小程序支付参数："+jsonData);
		System.out.println("头部参数："+JSONObject.toJSONString(signatureHeader));
		// 解密数据
		WxPayService wxPayService = WxPayDriver.handler(ClientEnum.MNP.getCode());
		WxPayOrderNotifyV3Result.DecryptNotifyResult notifyResult = wxPayService.parseOrderNotifyV3Result(jsonData, signatureHeader).getResult();

		// 取出数据
		String transactionId = notifyResult.getTransactionId();
		String outTradeNo = notifyResult.getOutTradeNo();
		String attach =  notifyResult.getAttach();

		// 处理回调
		iPayService.handlePaidNotify(attach, outTradeNo, transactionId);
		return AjaxResult.success();
	}
	
	@NotLogin
	@PostMapping("/notifyFromWxpayPc")
	@ApiOperation("Pc微信支付回调")
	public String notifyFromWxpayPc(HttpServletRequest request, HttpServletResponse response) throws WxPayException {
	        try {
	            String timestamp = request.getHeader("Wechatpay-Timestamp");
	            String nonce = request.getHeader("Wechatpay-Nonce");
	            String serialNo = request.getHeader("Wechatpay-Serial");
	            String signature = request.getHeader("Wechatpay-Signature");

	            String result = HttpKit.readData(request);
	            // 需要通过证书序列号查找对应的证书，verifyNotify 中有验证证书的序列号
	            String plainText = WxPayKit.verifyNotify(serialNo, result, signature, nonce, timestamp,
	            		WxPayConfigUtils.APIV3KEY, WxPayConfigUtils.WXPAY_PLATFORMCERTPATH);
	            System.out.println("扫码支付返回结果："+plainText);
	            if (StrUtil.isNotEmpty(plainText)) {
	            	JSONObject parseObject = JSONObject.parseObject(plainText);
	            	System.out.println("返回的json数据："+parseObject);
	            	if("SUCCESS".equalsIgnoreCase(parseObject.getString("trade_state"))) {
//	            		JSONObject amount = parseObject.getJSONObject("amount");
//	            		Double total = amount.getDouble("total");
//	            		return updateWhenNotify(parseObject.getString("out_trade_no"), parseObject.getString("transaction_id"), String.valueOf(total/100));
	            		// 处理回调
						iPayService.handlePaidNotify("order", parseObject.getString("out_trade_no"), parseObject.getString("transaction_id"));
						RedisUtils.set(parseObject.getString("out_trade_no"), "success",300);
						return "success";
	            	}
	            }
	        } catch (Exception e) {
	            e.printStackTrace();
	        }
		return "fail";
	}
	

	@NotLogin
	@PostMapping("/notifyAliPay")
	@ApiOperation("支付宝支付回调")
	public AjaxResult<Object> notifyAliPay(HttpServletRequest request) throws AlipayApiException, WxPayException, UnsupportedEncodingException {
		Map<String, String> param = AliPayDriver.getNotifyParam(request.getParameterMap());
		try{
			if (!AliPayDriver.checkSign(param)){
				return AjaxResult.failed("签名验证错误！");
			}
		}catch (Exception e){
			System.out.println(e.getMessage());
			return AjaxResult.failed("支付宝异步回调通知异常！");
		}
		if ("TRADE_SUCCESS".equals(param.get("trade_status"))){
			String outTradeNo = param.get("out_trade_no");
			String transactionId = param.get("trade_no");
			String attach = URLDecoder.decode(param.get("passback_params"), "UTF-8");
			// 处理回调
			iPayService.handlePaidNotify(attach, outTradeNo, transactionId);
			return AjaxResult.success();
		}else {
			return AjaxResult.failed("支付失败！");
		}
	}

	@PostMapping("/payVip")
	@ApiOperation("购买会员")
	public AjaxResult<Object> payVip(@Validated @RequestBody PayVipValidate requestObj) throws Exception {
		Integer userId = LikeFrontThreadLocal.getUserId();
		Integer terminal = LikeFrontThreadLocal.getTerminal();
		return iPayService.payVip(requestObj.getBusinessId(), requestObj.getPayWay(), requestObj.getRedirectUrl(), userId,requestObj.getCode(),terminal);
	}

	/**
	 * 用于支付宝回调
	 */
	@NotLogin
	@RequestMapping(value = "/notifyFromAlipay", method = { RequestMethod.POST, RequestMethod.GET })
	public String notifyFromAlipay(HttpServletRequest httpServletRequest) {
		System.out.println("进入支付宝回调============");
		Map<String, String> params = new HashMap<>();
		Map<String, String[]> requestParams = httpServletRequest.getParameterMap();
		for (Iterator<String> iter = requestParams.keySet().iterator(); iter.hasNext();) {
			String name = (String) iter.next();
			String[] values = (String[]) requestParams.get(name);
			String valueStr = "";
			for (int i = 0; i < values.length; i++) {
				valueStr = (i == values.length - 1) ? valueStr + values[i] : valueStr + values[i] + ",";
			}
			// 乱码解决，这段代码在出现乱码时使用。
			// valueStr = new String(valueStr.getBytes("ISO-8859-1"), "utf-8",token);
			params.put(name, valueStr);
		}
		return iPayService.notifyFromAlipay(params);
	}

	/**
	 * 用于微信回调
	 */
	@NotLogin
	@RequestMapping(value = "/notifyFromWxpay", method = { RequestMethod.POST, RequestMethod.GET })
	public String notifyFromWxpay(HttpServletRequest httpServletRequest) {
		InputStream is = null;
		String xmlBack = "<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[报文为空]]></return_msg></xml> ";
		try {
			is = httpServletRequest.getInputStream();
			// 将InputStream转换成String
			BufferedReader reader = new BufferedReader(new InputStreamReader(is));
			StringBuilder sb = new StringBuilder();
			String line = null;
			while ((line = reader.readLine()) != null) {
				sb.append(line + "\n");
			}
			xmlBack = iPayService.notifyFromWxpay(sb.toString());
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if (is != null) {
				try {
					is.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
		return xmlBack;
	}

	/**
	 * 	快点商城下单 微信回到
	 * @param httpServletRequest
	 * @return
	 */
	@NotLogin
	@RequestMapping(value = "/notifyFromWxpayMall", method = { RequestMethod.POST, RequestMethod.GET })
	public String notifyFromWxpayMall(HttpServletRequest httpServletRequest) {
		InputStream is = null;
		String xmlBack = "<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[报文为空]]></return_msg></xml> ";
		try {
			is = httpServletRequest.getInputStream();
			// 将InputStream转换成String
			BufferedReader reader = new BufferedReader(new InputStreamReader(is));
			StringBuilder sb = new StringBuilder();
			String line = null;
			while ((line = reader.readLine()) != null) {
				sb.append(line + "\n");
			}
			Map<String, String> resultMap = WXPayUtil.xmlToMap(sb.toString());
			WXPay wxPay = new WXPay(wxConfig);
			if (wxPay.isPayResultNotifySignatureValid(resultMap)) {
				String returnCode = resultMap.get("return_code");  //状态
				String orderNo = resultMap.get("out_trade_no");//商户订单号
				String tradeNo = resultMap.get("transaction_id"); //微信订单号
				//String totalfee = resultMap.get("total_fee"); //微信订单号
				if (returnCode.equals("SUCCESS")) {
					// 处理回调
					iPayService.handlePaidNotify("order", orderNo, tradeNo);
					return "success";
				}
			}

		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if (is != null) {
				try {
					is.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
		return xmlBack;
	}

	/** 
	 * 	支付宝商城下单回调
	 * @param httpServletRequest
	 * @return
	 * @throws AlipayApiException 
	 */
	@NotLogin
	@RequestMapping(value = "/notifyFromAlipayMall", method = { RequestMethod.POST, RequestMethod.GET })
	public String notifyFromAlipayMall(HttpServletRequest httpServletRequest) throws AlipayApiException {
		System.out.println("进入支付宝回调notifyFromAlipayMall============");
		try {
			Map<String, String> params = new HashMap<>();
			Map<String, String[]> requestParams = httpServletRequest.getParameterMap();
			for (Iterator<String> iter = requestParams.keySet().iterator(); iter.hasNext();) {
				String name = (String) iter.next();
				String[] values = (String[]) requestParams.get(name);
				String valueStr = "";
				for (int i = 0; i < values.length; i++) {
					valueStr = (i == values.length - 1) ? valueStr + values[i] : valueStr + values[i] + ",";
				}
				// 乱码解决，这段代码在出现乱码时使用。
				params.put(name, valueStr);
			}
			boolean flag = AlipaySignature.rsaCertCheckV1(params, AliPayConfigUtils.PUBLICCERTRAS2PATH, "UTF-8", "RSA2");
			if (flag) {
				String tradeStatus = params.get("trade_status");
				//签名验证通过,验证支付结果
				if ("TRADE_FINISHED".equals(tradeStatus)
						|| "TRADE_SUCCESS".equals(tradeStatus)) {
					String orderNo = params.get("out_trade_no");
					String tradeNo = params.get("trade_no");
					//String totalAmount = params.get("total_amount");
					iPayService.handlePaidNotify("order", orderNo, tradeNo);
					return "success";
				}
			}
		}catch (Exception e) {
			e.printStackTrace();
		}
		return "fail";
	}
	
	/**
	 * 	获取订单状态
	 * @return
	 */
	@GetMapping(value = "/getOrderStatus")
	public AjaxResult<Object> getOrderStatus(String orderNo) {
		if(StringUtils.isEmpty(orderNo)) {
			return AjaxResult.failed("orderNo is null");
		}
		// 0=待支付 1=已支付 2=已过期
		Integer status = 0;
		Object key = RedisUtils.get(orderNo);
		if(null != key) {
			String order = key.toString();
			if("getOrder".equals(order)) {
				status = 0;
			}else if("success".equals(order)){
				status = 1;
			}
		}else {
			status = 2;
		}
		return AjaxResult.success("succ",status);
	}
}
